﻿using System;
using System.Threading;

namespace PoolKit
{
    internal class RegistrationHandle
    {
        private readonly Waitable<RegisteredWaitHandle> _handle = new Waitable<RegisteredWaitHandle>();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="handle"></param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="InvalidOperationException"></exception>
        public void SetHandle(RegisteredWaitHandle handle)
        {
            _handle.Initialize(handle);
        }

        /// <summary>
        /// Note: blocks until handle is set to unregister it
        /// </summary>
        public void Unregister()
        {
            UnregisterInternal(null);
        }

        /// <summary>
        /// Note: blocks until handle is set to unregister it and until pooled task is either completed or successfully unregistered
        /// </summary>
        public void Unregister(WaitHandle waitHandleSetWhenWaitReturnsOrUnregisters)
        {
            if (waitHandleSetWhenWaitReturnsOrUnregisters == null)
                throw new ArgumentNullException("waitHandleSetWhenWaitReturnsOrUnregisters");

            UnregisterInternal(waitHandleSetWhenWaitReturnsOrUnregisters);
        }

        private void UnregisterInternal(WaitHandle handleSignalingUnregistrationOrCompletion)
        {
            var handle = _handle.WaitUntilValueIsSet();

            handle.Unregister(handleSignalingUnregistrationOrCompletion);

            if (handleSignalingUnregistrationOrCompletion != null)
            {
                handleSignalingUnregistrationOrCompletion.WaitOne();
            }
        }
    }
}